// Copyright (c) 2022 CHANGLEI. All rights reserved.

import 'package:aircraft_war/bloc/game_state_cubit.dart';
import 'package:aircraft_war/commons/constants.dart';
import 'package:aircraft_war/components/bullet_supply.dart';
import 'package:aircraft_war/components/enemy_aircraft.dart';
import 'package:aircraft_war/components/firepower_supply.dart';
import 'package:aircraft_war/components/main_game.dart';
import 'package:aircraft_war/enums/aircraft_state.dart';
import 'package:aircraft_war/generated/assets.dart';
import 'package:flame/collisions.dart';
import 'package:flame/components.dart';
import 'package:flame/flame.dart';
import 'package:flame/input.dart';

final _aliveSprites = [
  Sprite(Flame.images.fromCache(Images.me1)),
  Sprite(Flame.images.fromCache(Images.me2)),
];
final _destroySprites = [
  Sprite(Flame.images.fromCache(Images.me1)),
  Sprite(Flame.images.fromCache(Images.me_destroy_1)),
  Sprite(Flame.images.fromCache(Images.me_destroy_2)),
  Sprite(Flame.images.fromCache(Images.me_destroy_3)),
  Sprite(Flame.images.fromCache(Images.me_destroy_4)),
];

/// Created by changlei on 2022/5/16.
///
/// 飞机
class Aircraft extends PositionComponent with Draggable, GestureHitboxes, HasGameRef<MainGame>, CollisionCallbacks {
  /// 飞机
  Aircraft() : super(size: aircraftSize);

  late final _aircraft = SpriteAnimationGroupComponent<AircraftState>(
    animations: {
      AircraftState.alive: SpriteAnimation.spriteList(
        _aliveSprites,
        stepTime: 0.1,
      ),
      AircraftState.destroy: SpriteAnimation.spriteList(
        _destroySprites,
        stepTime: 0.1,
        loop: false,
      )..onComplete = _onDestroy,
    },
    size: size,
    current: AircraftState.alive,
  );

  Vector2? _dragDeltaPosition;

  /// 是否存活
  bool get isActive => _aircraft.current != AircraftState.destroy;

  /// 重置
  void reset() {
    for (var element in [...?_aircraft.animations?.values]) {
      element.reset();
    }
    _aircraft.current = AircraftState.alive;
  }

  @override
  Future<void> onLoad() async {
    await super.onLoad();
    await add(_aircraft);
    await add(PolygonHitbox.relative(
      [
        Vector2(0, -1.0),
        Vector2(-1.0, 0.2),
        Vector2(-1.0, 0.5),
        Vector2(1.0, 0.5),
        Vector2(1.0, 0.2),
      ],
      parentSize: size,
    ));
  }

  @override
  bool onDragStart(DragStartInfo info) {
    _dragDeltaPosition = info.eventPosition.game - position;
    return false;
  }

  @override
  bool onDragUpdate(DragUpdateInfo info) {
    final dragDeltaPosition = _dragDeltaPosition;
    if (dragDeltaPosition == null || !gameRef.isRunning) {
      return true;
    }
    final position = info.eventPosition.game - dragDeltaPosition;
    final tempXPosition = Vector2(position.x, this.position.y);
    final tempYPosition = Vector2(this.position.x, position.y);
    final newPosition = this.position.clone();
    if (_containsPoint(tempXPosition)) {
      newPosition.x = tempXPosition.x;
    }
    if (_containsPoint(tempYPosition)) {
      newPosition.y = tempYPosition.y;
    }
    this.position = newPosition;
    return false;
  }

  bool _containsPoint(Vector2 point) => containsOfParent(point) && containsOfParent(point + size);

  @override
  bool onDragEnd(DragEndInfo info) {
    _dragDeltaPosition = null;
    return false;
  }

  @override
  bool onDragCancel() {
    _dragDeltaPosition = null;
    return false;
  }

  @override
  void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
    super.onCollision(intersectionPoints, other);
    if (!isActive || !gameRef.isRunning) {
      return;
    }
    if (other is EnemyAircraft) {
      _collisionEnemyAircraft(other);
    } else if (other is BulletSupply) {
      _collisionBulletSupply(other);
    } else if (other is FirepowerSupply) {
      _collisionFirepowerSupply(other);
    }
  }

  void _collisionEnemyAircraft(EnemyAircraft other) {
    if (!other.isActive) {
      return;
    }
    if (gameRef.aliveCubit.consume()) {
      _aircraft.current = AircraftState.destroy;
    } else {
      other.destroy();
    }
  }

  void _collisionBulletSupply(BulletSupply other) {
    gameRef.bulletCubit.supply();
  }

  void _collisionFirepowerSupply(FirepowerSupply other) {
    gameRef.firepowerCubit.supply();
  }

  void _onDestroy() {
    removeFromParent();
    gameRef.stateCubit.stop();
  }
}
